001 /* 002 * Copyright 2004-2005 Stephen McConnell 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 013 * implied. 014 * 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package net.dpml.tools.tasks; 020 021 import java.io.File; 022 import java.util.ArrayList; 023 import java.util.List; 024 025 import net.dpml.library.info.Scope; 026 import net.dpml.library.Resource; 027 028 import org.apache.tools.ant.BuildException; 029 import org.apache.tools.ant.Project; 030 import org.apache.tools.ant.taskdefs.Javadoc; 031 import org.apache.tools.ant.taskdefs.Javadoc.AccessType; 032 import org.apache.tools.ant.types.DirSet; 033 import org.apache.tools.ant.types.Path; 034 035 /** 036 * Build the javadoc for a project. 037 * 038 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 039 * @version 1.1.1 040 */ 041 public class JavadocTask extends ResourceTask 042 { 043 //----------------------------------------------------------------------- 044 // static 045 //----------------------------------------------------------------------- 046 047 private static final String JAVADOC_TASK_NAME = "javadoc"; 048 049 /** 050 * Property key for declaration of an overriding access level. 051 */ 052 public static final String JAVADOC_ACCESS_KEY = "project.javadoc.access"; 053 054 /** 055 * Property key for declaration of the linksource option. 056 */ 057 public static final String JAVADOC_LINK_SOURCE_KEY = "project.javadoc.linksource"; 058 059 //----------------------------------------------------------------------- 060 // state 061 //----------------------------------------------------------------------- 062 063 private String m_title; 064 private List m_links = new ArrayList(); 065 private List m_groups = new ArrayList(); 066 private File m_overview; 067 private AccessType m_access; 068 private File m_dest; 069 070 //----------------------------------------------------------------------- 071 // JavadocTask 072 //----------------------------------------------------------------------- 073 074 /** 075 * Task initialization. 076 */ 077 public void init() 078 { 079 if( !isInitialized() ) 080 { 081 super.init(); 082 getContext().getPath( Scope.RUNTIME ); 083 } 084 } 085 086 /** 087 * Set the javadoc title. 088 * @param title the title 089 */ 090 public void setTitle( final String title ) 091 { 092 m_title = title; 093 } 094 095 /** 096 * Set the javadoc overview file. 097 * @param overview the overview file 098 */ 099 public void setOverview( final File overview ) 100 { 101 m_overview = overview; 102 } 103 104 /** 105 * Override the default destination. 106 * @param dir the destination directory 107 */ 108 public void setDest( final File dir ) 109 { 110 m_dest = dir; 111 } 112 113 /** 114 * Create and add a new link to the javadoc run. 115 * @return the new link 116 */ 117 public Link createLink() 118 { 119 final Link link = new Link(); 120 m_links.add( link ); 121 return link; 122 } 123 124 /** 125 * Create and add a new group to the javadoc defintion. 126 * @return the new group 127 */ 128 public Group createGroup() 129 { 130 final Group group = new Group(); 131 m_groups.add( group ); 132 return group; 133 } 134 135 /** 136 * Set the documentation access level. 137 * @param access the access level 138 */ 139 public void setAccess( AccessType access ) 140 { 141 m_access = access; 142 } 143 144 //----------------------------------------------------------------------- 145 // Task 146 //----------------------------------------------------------------------- 147 148 /** 149 * Task execution. 150 * @exception BuildException if a build error occurs 151 */ 152 public void execute() throws BuildException 153 { 154 final Resource resource = getResource(); 155 156 log( "Generating javadoc for project: " + resource, Project.MSG_VERBOSE ); 157 158 File api = getDestination(); 159 mkDir( api ); 160 161 // 162 // construct the classpath by getting all of the classpaths for 163 // all of the projects within the module 164 // 165 166 Resource[] providers = resource.getClasspathProviders( Scope.RUNTIME ); 167 final Path classpath = getContext().createPath( providers, true, true ); 168 process( resource, classpath, api ); 169 } 170 171 private File getDestination() 172 { 173 if( null == m_dest ) 174 { 175 return getContext().getTargetReportsJavadocDirectory(); 176 } 177 else 178 { 179 return m_dest; 180 } 181 } 182 183 //----------------------------------------------------------------------- 184 // internal 185 //----------------------------------------------------------------------- 186 187 private Group[] getGroups() 188 { 189 return (Group[]) m_groups.toArray( new Group[0] ); 190 } 191 192 private void process( 193 final Resource resource, final Path classpath, final File root ) 194 { 195 log( "Preparing javadoc for output to: " + root ); 196 197 final Javadoc javadoc = (Javadoc) getProject().createTask( JAVADOC_TASK_NAME ); 198 javadoc.setTaskName( getTaskName() ); 199 javadoc.init(); 200 javadoc.setDestdir( root ); 201 javadoc.setUse( true ); 202 javadoc.createClasspath().add( classpath ); 203 204 final Path source = javadoc.createSourcepath(); 205 addSourcePath( resource, javadoc, source ); 206 207 if( null == m_access ) 208 { 209 String access = getContext().getProperty( JAVADOC_ACCESS_KEY, "protected" ); 210 AccessType type = new AccessType(); 211 type.setValue( access ); 212 javadoc.setAccess( type ); 213 } 214 else 215 { 216 javadoc.setAccess( m_access ); 217 } 218 219 if( "true".equals( getContext().getProperty( JAVADOC_LINK_SOURCE_KEY, "false" ) ) ) 220 { 221 javadoc.setLinksource( true ); 222 } 223 224 aggregateLinks( javadoc, resource ); 225 Link[] links = (Link[]) m_links.toArray( new Link[0] ); 226 for( int i=0; i<links.length; i++ ) 227 { 228 Link link = links[i]; 229 Javadoc.LinkArgument arg = javadoc.createLink(); 230 String href = link.getHref(); 231 log( "Adding link: " + href ); 232 arg.setHref( href ); 233 } 234 235 if( null == m_title ) 236 { 237 final String title = resource.getName() + " API"; 238 javadoc.setDoctitle( title ); 239 } 240 else 241 { 242 javadoc.setDoctitle( m_title ); 243 } 244 245 if( null != m_overview ) 246 { 247 javadoc.setOverview( m_overview ); 248 } 249 250 Group[] groups = getGroups(); 251 for( int i=0; i < groups.length; i++ ) 252 { 253 Group group = groups[i]; 254 Javadoc.GroupArgument jgroup = javadoc.createGroup(); 255 jgroup.setTitle( group.getTitle() ); 256 Group.Package[] packages = group.getPackages(); 257 for( int j=0; j < packages.length; j++ ) 258 { 259 Javadoc.PackageName name = new Javadoc.PackageName(); 260 name.setName( packages[j].getName() ); 261 jgroup.addPackage( name ); 262 } 263 } 264 265 log( "Generating: " + resource.getName() + " API" ); 266 javadoc.execute(); 267 } 268 269 private void aggregateLinks( Javadoc task, Resource resource ) 270 { 271 String path = resource.getResourcePath(); 272 ArrayList list = new ArrayList(); 273 Resource[] providers = resource.getAggregatedProviders( Scope.RUNTIME, true, false ); 274 for( int i=0; i<providers.length; i++ ) 275 { 276 Resource provider = providers[i]; 277 if( !provider.getResourcePath().startsWith( path ) ) 278 { 279 String source = provider.getProperty( "project.api.root" ); 280 if( null != source ) 281 { 282 log( "Adding provider link: " + source + " from " + provider ); 283 Javadoc.LinkArgument arg = task.createLink(); 284 arg.setHref( source ); 285 } 286 } 287 } 288 } 289 290 private void addSourcePath( Resource resource, Javadoc javadoc, Path source ) 291 { 292 // 293 // check for a classic src directory 294 // 295 296 if( null != resource.getBaseDir() ) 297 { 298 File src = new File( resource.getBaseDir(), "target/build/main" ); 299 if( src.exists() ) 300 { 301 log( "Adding src path: " + src ); 302 source.createPathElement().setLocation( src ); 303 final DirSet packages = new DirSet(); 304 packages.setDir( src ); 305 packages.setIncludes( "**/*" ); 306 javadoc.addPackageset( packages ); 307 } 308 } 309 310 String path = resource.getResourcePath(); 311 Resource[] providers = resource.getAggregatedProviders( Scope.RUNTIME, true, false ); 312 for( int i=0; i<providers.length; i++ ) 313 { 314 Resource provider = providers[i]; 315 if( provider.getResourcePath().startsWith( path ) ) 316 { 317 String flag = provider.getProperty( "project.javadoc.exclude", "false" ); 318 if( "false".equals( flag ) ) 319 { 320 File basedir = provider.getBaseDir(); 321 if( null != basedir ) 322 { 323 File src = new File( basedir, "target/build/main" ); 324 if( src.exists() ) 325 { 326 log( "Adding src path: " + src ); 327 source.createPathElement().setLocation( src ); 328 final DirSet packages = new DirSet(); 329 packages.setDir( src ); 330 packages.setIncludes( "**/**" ); 331 javadoc.addPackageset( packages ); 332 } 333 } 334 } 335 } 336 } 337 } 338 339 //----------------------------------------------------------------------- 340 // static classes 341 //----------------------------------------------------------------------- 342 343 /** 344 * Delcaration of a link. 345 */ 346 public class Link 347 { 348 private String m_href; 349 350 /** 351 * Creation of a new link instance. 352 */ 353 public Link() 354 { 355 m_href = null; 356 } 357 358 /** 359 * Set the href attrbute for the api packagelist base. 360 * @param href the href to the packacke list base 361 */ 362 public void setHref( final String href ) 363 { 364 m_href = href; 365 } 366 367 /** 368 * Get the href attribute. 369 * @return the href attriute value 370 */ 371 public String getHref() 372 { 373 if( null != m_href ) 374 { 375 return m_href; 376 } 377 else 378 { 379 final String error = 380 "Link element must contain an 'href' attribute."; 381 throw new BuildException( error, getLocation() ); 382 } 383 } 384 } 385 386 /** 387 * Defintion of a package group. 388 */ 389 public static class Group 390 { 391 private String m_title; 392 private ArrayList m_packages = new ArrayList(); 393 394 /** 395 * Set the package group title. 396 * @param title the package group title 397 */ 398 public void setTitle( String title ) 399 { 400 m_title = title; 401 } 402 403 /** 404 * Return the package group title. 405 * @return the title 406 */ 407 public String getTitle() 408 { 409 if( null == m_title ) 410 { 411 final String error = 412 "Required 'title' attribute on group element undefined."; 413 throw new BuildException( error ); 414 } 415 else 416 { 417 return m_title; 418 } 419 } 420 421 /** 422 * Return the packages within the group. 423 * @return the array of packages 424 */ 425 public Group.Package[] getPackages() 426 { 427 return (Group.Package[]) m_packages.toArray( new Group.Package[0] ); 428 } 429 430 /** 431 * Create and add a new package. 432 * @return the new package 433 */ 434 public Group.Package createPackage() 435 { 436 final Package pkg = new Package(); 437 m_packages.add( pkg ); 438 return pkg; 439 } 440 441 /** 442 * Defintionof a package. 443 */ 444 public static class Package 445 { 446 private String m_name; 447 448 /** 449 * Set the package name. 450 * @param name the package name 451 */ 452 public void setName( String name ) 453 { 454 m_name = name; 455 } 456 457 /** 458 * Return the package name. 459 * @return the name 460 */ 461 public String getName() 462 { 463 if( null == m_name ) 464 { 465 final String error = 466 "Required 'name' attribute on package element undefined."; 467 throw new BuildException( error ); 468 } 469 else 470 { 471 return m_name; 472 } 473 } 474 } 475 } 476 }